﻿#include "my_socket.h"
#include "tcp_net_handler.h"

TcpNetChannel::TcpNetChannel()
    : MySocket(TCP4_SOCKET)
{

}

int TcpNetChannel::net_init(const TcpNetType type,
                            const unsigned short port,
                            const int max_conn)
{
    net_type_ = type;
    if (net_type_ == TCP_SVR)
    {
        svr_port_ = port;

        if (max_conn > MAX_ACCEPT_CLIENT_NUM)
        {
            std::cout << "listening conn exceed the max accepted conn" << std::endl;
            return ERROR_INIT_NET;
        }
        max_conn_ = max_conn;
    }

    return initialize();
}

int TcpNetChannel::service_start()
{
    if (net_type_ != TCP_SVR)
    {
        return ERROR_START_SERVICE;
    }

    int ret = TCP_HANDLER_PROC_SUCC;
    // 绑定一下端口
    ret = bind_port(svr_port_);
    if (ret != MYSOCKET_PROC_SUCC)
    {
        std::cout << "bind port error" << std::endl;
        return ret;
    }

    // 开始侦听
    ret = svr_listen(max_conn_);
    if (ret != MYSOCKET_PROC_SUCC)
    {
        std::cout << "svr listen error" << std::endl;
        return ret;
    }

    return TCP_HANDLER_PROC_SUCC;
}

TcpNetChannel *TcpNetChannel::new_client()
{
    TcpNetChannel *new_channel = new TcpNetChannel;
    int ret = accept_client(new_channel);
    if (ret != MYSOCKET_PROC_SUCC)
    {
        std::cout << "accept client error" << std::endl;
        delete new_channel; 
        
        return NULL;
    }

    return new_channel;
}

int TcpNetChannel::recv_frame(char *buf, const int framehead_len)
{
    char *temp = NULL;

    // 先接收4个字节，存储着整个数据帧的大小
    int first_recvlen = recv_data(&temp, 4);        
    if (first_recvlen == MySocket::ERROR_RECV_DATA
        || first_recvlen != 4)
    {
        return ERROR_RECV_DATA_FRAME;
    }

    if (temp == NULL)
    {
        // 肯定接收出错了
        std::cout << "recv data frame error" << std::endl;
        return ERROR_RECV_DATA_FRAME;
    }

    memcpy(buf, temp, first_recvlen);

    // 提取出帧头中的数据包长度
    int net_order = *(reinterpret_cast<int *>(temp));
    int bodylen = ntohl(net_order);
    
    // 计算还需要接收的数据包长度
    int left_recvlen = bodylen + framehead_len - first_recvlen;
    int recv_bytes = recv_data(&temp, left_recvlen);
    if (left_recvlen != recv_bytes || recv_bytes == MySocket::ERROR_RECV_DATA)
    {
        std::cout << "recv size of package is not correct" << std::endl;
        return ERROR_RECV_DATA_FRAME;
    }

    memcpy(buf + first_recvlen, temp, left_recvlen);

    return framehead_len + bodylen;
}

const char * TcpNetChannel::get_client_ip()
{
    return inet_ntoa(m_client_addr_.sin_addr);
}

unsigned short TcpNetChannel::get_client_port()
{
    return m_client_addr_.sin_port;
}
